package czy.demo.config;

import com.fasterxml.jackson.core.JsonParser;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.security.core.session.SessionRegistry;
import org.springframework.session.data.redis.RedisOperationsSessionRepository;
import org.springframework.session.security.SpringSessionBackedSessionRegistry;
import org.springframework.session.web.http.HeaderHttpSessionIdResolver;
import org.springframework.session.web.http.HttpSessionIdResolver;

/* spring session 配置类 */
@Configuration
public class SpringSessionConfig {

    public static final String SESSION_HEADER = "X-Auth-Token";

    @Lazy
    @Autowired
    private RedisOperationsSessionRepository sessionRepository;

    /* 基于X-Auth-Token的session解析器
    * 全局只有一个sessionId解析器
    */
    @Bean
    public HttpSessionIdResolver httpSessionIdResolver() {
        return new HeaderHttpSessionIdResolver(SESSION_HEADER);
    }

    /** session注册，安全框架中使用 */
    @Bean
    public SessionRegistry sessionRegistry(){
        return new SpringSessionBackedSessionRegistry<>(sessionRepository);
    }

    /** Jackson序列化，需要保证所有对象有默认构造函数
     * 目前不兼容 {@link org.springframework.security.authentication.UsernamePasswordAuthenticationToken}
     * 需要重写过滤器
     */
    @Configuration
    static class SpringSessionRepository implements BeanPostProcessor{

        @Override
        public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
            if(bean instanceof RedisOperationsSessionRepository){
                RedisOperationsSessionRepository redisSessionRepository = (RedisOperationsSessionRepository)bean;
                RedisTemplate redisTemplate = (RedisTemplate)redisSessionRepository.getSessionRedisOperations();
                StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
                GenericJackson2JsonRedisSerializer jsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
                redisTemplate.setKeySerializer(stringRedisSerializer);
                redisTemplate.setValueSerializer(jsonRedisSerializer);
                redisTemplate.setHashKeySerializer(stringRedisSerializer);
                redisTemplate.setHashValueSerializer(jsonRedisSerializer);
                redisTemplate.setStringSerializer(stringRedisSerializer);
                redisTemplate.setDefaultSerializer(jsonRedisSerializer);
                redisTemplate.setEnableDefaultSerializer(true);
                redisSessionRepository.setDefaultSerializer(jsonRedisSerializer);
            }
            return bean;
        }
    }
}
